﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Windows;

namespace personalplaner.services
{
    public interface IApplicationStyleService
    {
        void SelectStyle(string name);

        void AppendStyle(ResourceDictionary resource, string name);
    }

    public class ApplicationStyleService : IApplicationStyleService
    {
        List<string> _styles;
        public List<string> Styles
        {
            get
            {
                return _styles;
            }
            set
            {
                _styles = value;
            }
        }

        static Dictionary<string, ApplicationStyleItem> _stylesDictionary;

        public ApplicationStyleService()
        {
            if (_stylesDictionary == null)
                InitStyles();

            Styles = new List<string>();

            //Styles.Add("Default");
            foreach (string style in _stylesDictionary.Keys)
                Styles.Add(style);
        }

        private static void InitStyles()
        {
            _stylesDictionary = new Dictionary<string, ApplicationStyleItem>();

            var dark = new ApplicationStyleItem();
            dark.Add((ResourceDictionary)Application.LoadComponent(new Uri(@"personalplaner.common;;;component\resources/styles/DarkBrushes.xaml", UriKind.Relative)));
            dark.Add((ResourceDictionary)Application.LoadComponent(new Uri(@"personalplaner.common;;;component\resources/styles/dark/Styles.xaml", UriKind.Relative)));
            dark.Add((ResourceDictionary)Application.LoadComponent(new Uri(@"personalplaner.common;;;component\resources/styles/dark/MenuTabControl.xaml", UriKind.Relative)));
            dark.Add((ResourceDictionary)Application.LoadComponent(new Uri(@"personalplaner.common;;;component\resources/styles/dark/PlanMenuTemplate.xaml", UriKind.Relative)));
            //dark.Add((ResourceDictionary)Application.LoadComponent(new Uri(@"sage200.gui;;;component\resources/DefaultStyles.xaml", UriKind.Relative)));
            _stylesDictionary.Add("Dark", dark);

            var gray = new ApplicationStyleItem();
            gray.Add((ResourceDictionary)Application.LoadComponent(new Uri(@"personalplaner.common;;;component\resources/styles/gray/GrayBrushes.xaml", UriKind.Relative)));
            gray.Add((ResourceDictionary)Application.LoadComponent(new Uri(@"personalplaner.common;;;component\resources/styles/gray/collapsiblePanel.xaml", UriKind.Relative)));
            gray.Add((ResourceDictionary)Application.LoadComponent(new Uri(@"personalplaner.common;;;component\resources/styles/gray/Styles.xaml", UriKind.Relative)));
            gray.Add((ResourceDictionary)Application.LoadComponent(new Uri(@"personalplaner.common;;;component\resources/styles/gray/MenuTabControl.xaml", UriKind.Relative)));
            gray.Add((ResourceDictionary)Application.LoadComponent(new Uri(@"personalplaner.common;;;component\resources/styles/gray/PlanMenuTemplate.xaml", UriKind.Relative)));
            _stylesDictionary.Add("Gray", gray);
        }

        public void SelectStyle(string name)
        {
            if (name == null)
                return;

            if (_stylesDictionary == null)
                InitStyles();

            if (Application.Current.Resources == null)
                Application.Current.Resources = new ResourceDictionary();

            if (string.IsNullOrEmpty(name))
            {
                UnloadResources(Application.Current.Resources);
            }
            else
            {
                if (_stylesDictionary.ContainsKey(name))
                {
                    UnloadResources(Application.Current.Resources);

                    var item = _stylesDictionary[name];
                    foreach (var dir in item)
                    {
                        //Application.Current.Resources.MergedDictionaries.Add(dir);
                        Application.Current.Resources.MergedDictionaries.Insert(0, dir);
                    }
                    item.IsLoaded = true;
                }
                else
                {
                    //Application.Current.Resources.Clear();
                    //Application.Current.Resources.MergedDictionaries.Clear();
                    UnloadResources(Application.Current.Resources);
                }
            }
        }

        public void AppendStyle(ResourceDictionary resource, string name)
        {
            if (string.IsNullOrEmpty(name))
            {
                UnloadResources(resource);
            }
            else
            {
                if (_stylesDictionary.ContainsKey(name))
                {
                    UnloadResources(resource);

                    var item = _stylesDictionary[name];
                    foreach (var dir in item)
                    {
                        if (!resource.MergedDictionaries.Contains(resource))
                            resource.MergedDictionaries.Add(dir);
                    }
                    item.IsLoaded = true;
                }
            }
        }

        private static void UnloadResources(ResourceDictionary resource)
        {
            foreach (var appstyle in _stylesDictionary.Values)
            {
                if (appstyle.IsLoaded)
                {
                    foreach (var item in appstyle)
                    {
                        //Application.Current.Resources.MergedDictionaries.Remove(item);
                        if (resource.MergedDictionaries.Contains(item))
                            resource.MergedDictionaries.Remove(item);
                    }
                }
            }
        }
    }

    internal class ApplicationStyleItem : IEnumerable<ResourceDictionary>
    {
        public ApplicationStyleItem()
        {
            Items = new List<ResourceDictionary>();
        }

        IList<ResourceDictionary> Items { get; set; }

        public bool IsLoaded { get; set; }

        public int Count
        {
            get
            {
                return Items.Count;
            }
        }

        public void Add(ResourceDictionary resource)
        {
            //Items.Add(resource);
            Items.Add(resource);
        }

        #region IEnumerable Implementation

        public IEnumerator<ResourceDictionary> GetEnumerator()
        {
            return new ApplicationStyleItemEnumerator(this);
        }

        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            return new ApplicationStyleItemEnumerator(this);
        }

        public struct ApplicationStyleItemEnumerator : IEnumerator<ResourceDictionary>
        {
            readonly ApplicationStyleItem collection;
            ResourceDictionary current;
            int index;

            internal ApplicationStyleItemEnumerator(ApplicationStyleItem collection)
            {
                this.collection = collection;
                this.current = default(ResourceDictionary);
                index = 0;
            }

            public void Dispose()
            {
            }

            public ResourceDictionary Current
            {
                get
                {
                    return current;
                }
            }

            object IEnumerator.Current
            {
                get
                {
                    return this.Current;
                }
            }

            public bool MoveNext()
            {
                if (index < collection.Count)
                {
                    //this.current = collection.Items[this.index];
                    this.current = collection.Items[this.index];
                    this.index++;
                    return true;
                }
                return false;
            }

            public void Reset()
            {
                index = 0;
                current = default(ResourceDictionary);
            }
        }

        #endregion
    }
}
